<?php
namespace Kuoqi\Worker;

use Kuoqi\Exception;
use Kuoqi\Worker\Socket;
/**
 * KuoqiWorker主要操作服务端模块
 * Class Server
 * @package Kuoqi\Worker
 * User kuoqi
 * Datetime 2022/3/24 9:02
 * Remark netstat -tlnp|grep 6519
 */
class Server extends Socket
{

    /**
     * 加密秘钥
     * @var string
     * User kuoqi
     * Datetime 2022/3/24 10:41
     * Remark
     */
    protected $password = 'm81jtgrx0fs0ys0ezbkqbnj2kg';
    /**
     * 加密数据偏移量
     * @var string
     * User kuoqi
     * Datetime 2022/3/24 10:41
     * Remark
     */
    protected $iv = '2n2jkcc3cah3x0ht';

    /**
     * lock文件
     * @var string
     * User kuoqi
     * Datetime 2022/3/24 21:56
     * Remark
     */
    protected $lock = '';

    /**
     * 设置当前进程的守护进程ID
     * @var int
     * User kuoqi
     * Datetime 2022/3/27 9:42
     * Remark
     */
    protected $PID = 0;

    protected $interval = 2;

    /**
     * 初始化
     * Server constructor.
     * @param $address
     * @param $port
     */
    public function __construct($address, $port)
    {
        parent::__construct($address, $port);

    }

    public function __destruct()
    {
        //$this->say('server destruct');
        parent::__destruct(); // TODO: Change the autogenerated stub
    }

    /**
     * 重写listen部分信息，让这部分为一个独立服务器靠近
     * User kuoqi
     * Datetime 2022/3/24 9:42
     * Remark
     */
    public function listen()
    {
        //让其它socket无法被挂载
        $socketArr = $this->sockets;$write = NULL;$except = NULL;

        //自动选择来消息的socket 如果是握手 自动选择主机
        //int socket_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] )
        //直接启用阻塞模式
        //这个服务的数据信息不能使用阻塞模式
        if(false ===@socket_select($socketArr, $write, $except, 0)){
            $this->debug("socket_select() failed, reason: " . socket_strerror(socket_last_error()));
        }
        //循环socket信息
        foreach ($socketArr as $k=>$socket){
            //不为主进程，直接不接收就好，这样应该是不占用进程信息的
            if ($socket == $this->master) {
                //针对这个的相关处理
                $client = socket_accept($this->master);
                //接收这个客户端了
                if ($client < 0){
                    //在接收之前，客户端死掉了，就是这个情况
                    $this->debug("socket_accept() failed");
                    continue;
                }

                $bytes = socket_recv($client,$buffer,2048,0);
                if ($bytes == 0){
                    $this->debug("socket_recv() failed");
                    continue;
                }
                //$this->sockets
                $this->doCommand($client, $buffer);
                //array_push($this->sockets, $client);
            }
        }
    }

    /**
     * 执行那些奇葩命令
     * @param $client 当前接受的客户端
     * @param $comm 命令内容
     * User kuoqi
     * Datetime 2022/3/24 10:16
     * Remark
     */
    public function doCommand($client,$commstring){
        $comm = \Kuoqi\Openssl::decode($commstring,'',$this->password,$this->iv,0);
        $comm = unserialize($comm);
        $commParser = new CommParser($comm);
        $commParser->init();//解析命令
        switch($commParser->getAction()){
            case 'start':$this->doCommandStart($commParser);break;//启动命令
        }
    }

    /**
     * 执行开始命令
     * @param $commParser
     * User kuoqi
     * Datetime 2022/3/31 16:11
     * Remark
     */
    public function doCommandStart($commParser){
        $comm = new $commParser->routes[0]();
        $pid = pcntl_fork();
        if($pid){
            //主进程
            //什么都不干，让后面的程序继续执行
            $this->say('命令主进程执行');
            //exit($pid);
        }else{
            $this->say('命令副进程11');
            while(true){
                $this->say($commParser->routes[0]);
                sleep(2);
            }
            $this->say('命令副进程222');
        }
    }

    /**
     * 检测lock文件的状态
     * @return bool
     * User kuoqi
     * Datetime 2022/3/24 22:12
     * Remark
     */
    public function checkPid(){
        //清除文件状态缓存
        clearstatcache(true,$this->lock);
        return is_file($this->lock)?true:false;
    }


    /**
     * 停止服务
     * User kuoqi
     * Datetime 2022/3/31 14:28
     * Remark
     */
    public function stop(){
        $this->say('to stop');
    }



    /**
     * 获取异常信息
     * @return string
     * User kuoqi
     * Datetime 2022/3/26 23:38
     * Remark
     */
    public function getError(){
        return $this->errmsg;
    }

}